﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace System.Dns.Toolkit.DnsServer {

    public class LockingPriorityQueue<TP, TV> : IPriorityQueue<TP, TV> {

        private readonly SortedDictionary<TP, ConcurrentQueue<TV>> _queues = new SortedDictionary<TP, ConcurrentQueue<TV>>();
        private readonly object _synchronize = new object();

        public void Enqueue(TP priority, TV value) {

            lock (_synchronize ) {
                ConcurrentQueue<TV> q;
                if (!_queues.TryGetValue(priority, out q)) {
                    q = new ConcurrentQueue<TV>();
                    _queues.Add(priority, q);
                }
                q.Enqueue(value);
            }

        }

        public bool TryDequeue(out TV value) {

            lock(_synchronize) {

                var keyValuePair = _queues.FirstOrDefault();
                var q = keyValuePair.Value;
                if (q == null) {
                    value = default(TV);
                    return false;
                }

                if (q.TryDequeue(out value)) {

                    if (q.IsEmpty) {
                        _queues.Remove(keyValuePair.Key);
                    }

                    return true;

                }
            }
            return false;
        }

        public bool IsEmpty {
            get {
                lock (_synchronize) {
                    return !_queues.Any();
                }
            }
        }

        public int Count {
            get {
                lock (_synchronize) {
                    return _queues.Values.Sum(q => q.Count);
                }
            }
        }

    }


}
